/*  Nanhill Data Bind JavaScript Library
 *  
 *  version 1.0.1 2006-03-31
 * 		add table bind.
 *
 *  (c) 2005 alin <xalinx@gmail.com>
 *	need Nhill util.js, prototype.js
 * 
 *  Nanhill javascript library is freely distributable under the terms 
 * 	of an Apache license. For details, see the Nanhill web site: 
 *  http://sourceforge.net/projects/nanhillplatform
/*--------------------------------------------------------------------------*/
/*
Object.extend(Sro.prototype, {
	bindReply : function(service, params, bindElemId) {
		this.remoteCall(service, params, function(reply) {
			NHbind.bind(bindElemId, reply.getResult());
		})
	}
});
*/
nh.bind = {};
nh.bind.bind = function(element, bindValue, options) {
	var elem = $(element);
	nh.Util.debug("bind element id: " + elem.id + ",tagName:" + elem.tagName);
	//alert(ele);
	switch(elem.tagName.toLowerCase()) {
		case "input": 
			switch (elem.type.toLowerCase()) {
				case "text": ;
				case "hidden": ;
				case "password": nh.bind.Factory.bindText(elem, bindValue); break;
				case "checkbox": ;
				case "radio": nh.bind.Factory.bindRadioOrCheckbox(elem, bindValue); break;
			}
			break;
		case "textarea":
			nh.bind.Factory.bindText(elem, bindValue);
			break; 
		case "table":
		case "tbody": 
		case "thead":
		case "tfoot":
			nh.bind.removeAllRows(elem);
			nh.bind.addRows(elem, bindValue, options.cellFuncs, options.cellCreator);
			break; 
		case "select": 
			nh.bind.Factory.bindSelect(elem, bindValue);
			break; 
		case "div":
		case "span":
			elem.innerHTML = bindValue;
			break;
		//TODO: add more bindings here 
		default :
			nh.Util.debug("no biding for this element.");
	}
};

nh.bind.Factory = {
	reportError: function(elem, value, msg) { 
		throw "Data bind failed: " + msg;
	},
	
	bindText: function(elem, value) { 
		elem.value = value;
	},
	
	bindRadioOrCheckbox: function(elem, value) {
		var ret = false;
		switch (typeof(value)) {
			case 'boolean': ret = value; break;
			case 'string': ret = (value == "1" || value == "true" || value == "yes"); break;
			case 'number': ret = (parseInt(value) == 1); break;
			default: ret = false;
		}
		elem.checked = ret;
	},

	bindSelect : function(elem, value) {
		//TODO: Check the data type
		if (typeof(value) != "object" || value.constructor != Array) {
			this.reportError(elem,value,"Array Type Needed for binding select!");
		}
		// delete all the nodes.
		while (elem.childNodes.length > 0) {
			elem.removeChild(elem.childNodes[0]);
		}
		
		// bind data
		for (var i = 0; i < value.length; i++) {
			var option = document.createElement("OPTION");
			var data = value[i];
			if (data == null || typeof(data) == "undefined") {
				option.value = "";
				option.text = "";
			}
			if (typeof(data) != 'object') {
				option.value = data;
				option.text = data;
			} else {
				option.value = data[elem.getAttribute("jvalue")];
				option.text = data[elem.getAttribute("jtext")];	
			}
			elem.options.add(option);
		}
	},

	bindRepeater:function(elem, value) {
		//TODO: implementation will be added.
	}

}
// {{ table creator
/**
 * Create rows inside a the table, tbody, thead or tfoot element (given by id).
 * @see http://getahead.ltd.uk/dwr/browser/tables
 */
nh.bind.addRows = function(ele, data, cellFuncs, options) {
  var orig = ele;
  ele = $(ele);
  if (ele == null) {
    nh.Util.debug("addRows() can't find an element with id: " + orig + ".");
    return;
  }
  if (!nh.bind._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
    nh.Util.debug("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + nh.Util.typeOf(ele));
    return;
  }
  if (!options) options = {};
  if (!options.rowCreator) options.rowCreator = nh.bind._defaultRowCreator;
  if (!options.cellCreator) options.cellCreator = nh.bind._defaultCellCreator;
  var tr, rowNum;
  if (nh.Util.isArray(data)) {
    for (rowNum = 0; rowNum < data.length; rowNum++) {
      options.rowData = data[rowNum];
      options.rowIndex = rowNum;
      options.rowNum = rowNum;
      options.data = null;
      options.cellNum = -1;
      tr = nh.bind._addRowInner(cellFuncs, options);
      if (tr != null) ele.appendChild(tr);
    }
  }
  else if (typeof data == "object") {
    rowNum = 0;
    for (var rowIndex in data) {
      options.rowData = data[rowIndex];
      options.rowIndex = rowIndex;
      options.rowNum = rowNum;
      options.data = null;
      options.cellNum = -1;
      tr = nh.bind._addRowInner(cellFuncs, options);
      if (tr != null) ele.appendChild(tr);
      rowNum++;
    }
  }
};

/**
 * @private Internal function to draw a single row of a table.
 */
nh.bind._addRowInner = function(cellFuncs, options) {
  var tr = options.rowCreator(options);
  if (tr == null) return null;
  for (var cellNum = 0; cellNum < cellFuncs.length; cellNum++) {
    var func = cellFuncs[cellNum];
    var td;
    //if (typeof func == "string") {
    //  options.data = func;
    //  options.cellNum = cellNum;
    //  td = options.cellCreator(options);
    //  td.appendChild(document.createTextNode(func));
    //}
    //else {
      var reply = func(options.rowData);
      options.data = reply;
      options.cellNum = cellNum;
      td = options.cellCreator(options);
      if (nh.bind._isHTMLElement(reply, "td")) td = reply;
      else if (nh.bind._isHTMLElement(reply)) td.appendChild(reply);
      else td.innerHTML = reply;
    //}
    tr.appendChild(td);
  }
  return tr;
};

/**
 * @private Default row creation function
 */
nh.bind._defaultRowCreator = function(options) {
  return document.createElement("tr");
};

/**
 * @private Default cell creation function
 */
nh.bind._defaultCellCreator = function(options) {
  return document.createElement("td");
};

/**
 * Remove all the children of a given node.
 * @see http://getahead.ltd.uk/dwr/browser/tables
 */
nh.bind.removeAllRows = function(ele) {
  var orig = ele;
  ele = $(ele);
  if (ele == null) {
    nh.Util.debug("removeAllRows() can't find an element with id: " + orig + ".");
    return;
  }
  if (!nh.bind._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
    nh.Util.debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + nh.Util.typeOf(ele));
    return;
  }
  while (ele.childNodes.length > 0) {
    ele.removeChild(ele.firstChild);
  }
};

/**
 * @private Is the given node an HTML element (optionally of a given type)?
 * @param ele The element to test
 * @param nodeName eg "input", "textarea" - check for node name (optional)
 *         if nodeName is an array then check all for a match.
 */
nh.bind._isHTMLElement = function(ele, nodeName) {
  if (ele == null || typeof ele != "object" || ele.nodeName == null) {
    return false;
  }

  if (nodeName != null) {
    var test = ele.nodeName.toLowerCase();

    if (typeof nodeName == "string") {
      return test == nodeName.toLowerCase();
    }

    if (nh.Util.isArray(nodeName)) {
      var match = false;
      for (var i = 0; i < nodeName.length && !match; i++) {
        if (test == nodeName[i].toLowerCase()) {
          match =  true;
        }
      }
      return match;
    }

    nh.Util.debug("nh.bind._isHTMLElement was passed test node name that is neither a string or array of strings");
    return false;
  }

  return true;
};
//}}

//{{ pagination 
nh.Pagination = Class.create();
nh.Pagination.prototype = {
	initialize: function(methodName, imgLoc) {
		this._pageId = null;
		this._pageSize = null;
		this._rowStartIndex = null;
		this._sum = null;
		this._pageTotal = null;
		this._methodName = methodName;
		this._imgLoc = imgLoc;
	},
	
	page: function(sum, pageId, pageSize) {
		this._pageSize = pageSize;
		this._sum = sum;
		this._pageId = pageId;
		this._rowStartIndex =  (this._pageId - 1) * this._pageSize + 1;	
		this._pageTotal = parseInt(this._sum / this._pageSize);
		this._pageTotal = 0 == this._sum % this._pageSize ? this._pageTotal : this._pageTotal + 1;
	},
	
	getRowStartIndex: function() {
		return this._rowStartIndex;	
	},
		
	_addPage : function(index) {
		return index == this._pageId ? index + "&nbsp;" : "<a href='#' onclick='" + this._methodName + "(" + index +  ")'>" + index + "</a>,&nbsp;";
	},
	
	_getPre : function() {
		return this._pageId == 1 ? "" : "<img  src=\"" + this._imgLoc + "/arrow_back.gif\" alt=\"上一页\" onclick=\"" + this._methodName + "(" + (this._pageId - 1) + ");\"/>&nbsp;";
	},
	
	_getNext : function() {
		return this._pageId == this._pageTotal || 1 == this._pageTotal ? "" : "<img  src=\"" + this._imgLoc + "/arrow_forward.gif\" alt=\"下一页\" onclick=\"" + this._methodName + "(" + (this._pageId + 1) + ");\"/>&nbsp;";
		//"<a href='#' onclick='"+ this._methodName +"(" + (this._pageId + 1) + ")'>" + "下一页</a>&nbsp;";
	},
	
	createIndex : function () {
		//alert(this._sum + ":" + this._pageId + ":" + this._pageSize);
		var maxBlock = 6;
		var block = 3;
		var all = maxBlock + block;
		var indexs = "";
		if (0 == this._sum || 1 == this._pageTotal) {
			return indexs;
		}

		indexs += "<div style='float:left;text-align:left;height:16px;'>共" + this._pageTotal + "页" + this._sum + "条," + "每页" + this._pageSize + "条,当前第"+ this._pageId +"页</div>"; 
		indexs += "<div style=\"text-align:right;height:16px;\">";
		//alert(this.getPre());
		indexs += this._getPre();
		// total: 1 ~ 9
		if(this._pageTotal <= all) {
			for (var i = 1; i <= this._pageTotal; i ++) {
				indexs += this._addPage(i);
			}
		// total: 10 ~
		} else {
			// pageId: 1 ~ 5
			if(this._pageId <= maxBlock - 1 ) {
				for (var i = 1; i <= this._pageId + 1 || i <= block; i ++) {
					indexs += this._addPage(i);
				}
				indexs += "&nbsp;...&nbsp;";
				for (var i = this._pageTotal - 2; i <= this._pageTotal; i ++) {
					indexs += this._addPage(i);
				}				
			// pageId: 6 ~
			} else {
				for (var i = 1; i <= block; i ++) {
					indexs += this._addPage(i);
				}
				indexs += "&nbsp;...&nbsp;";
				
				var leftEdge = this._pageTotal - maxBlock + 1;
				//alert(leftEdge);
				if (this._pageId > leftEdge) {
					for (var i = leftEdge; i <= this._pageTotal; i ++) {
						indexs += this._addPage(i);
					}					
				} else {
					for (var i = this._pageId - 1; i <= this._pageId + 1; i ++) {
						indexs += this._addPage(i);
					}
					indexs += "&nbsp;...&nbsp;";
					for (var i = this._pageTotal - 2; i <= this._pageTotal; i ++) {
						indexs += this._addPage(i);
					}
				}
			} 
		}	
		indexs += this._getNext();
		indexs += "</div>";
		return indexs;
	}
}
//}}
